#!/usr/bin/perl
use FindBin;
use lib "$FindBin::Bin/lib";
use lib "$FindBin::Bin/pllib/lib/perl5";

use strict;
use Getopt::Long;
use File::Basename;

sub usage {
    my $pname = $FindBin::Script;

    print("Usage: $pname [-verbose <0|1>] --failcheck <0|1> --logpath <log path pattern> --maxsize <max log fetch size before eof>  [--op <and|or>] <pattern1>,<pattern2>...\n");
    print("       -verbose <0|1>:                     verbose\n");
    print("       --failcheck:                  check for fail status\n");
    print("       --logpath <log path pattern>: log path, wildcard supported\n");
    print("       --maxsize <max fetch size>:   max mega bytes read from log file before eof, default:16\n");
    print("       --op <and|or>                 patterns operator and or or\n");
    print("       <pattern>                     key word pattern\n");

    exit(1);
}

sub matchPatterns {
    my ( $txt, $patterns, $operator ) = @_;
    my $matched = 0;

    if ( $operator eq 'and' ) {
        $matched = 1;
        foreach my $pattern (@$patterns) {
            if ( $txt !~ /$pattern/ ) {
                $matched = 0;
                last;
            }
        }
    }
    else {
        $matched = 0;
        foreach my $pattern (@$patterns) {
            if ( $txt =~ /$pattern/ ) {
                $matched = 1;
                last;
            }
        }

    }

    return $matched;
}

sub matchLogLines {
    my ( $logFilePath, $maxSize, $patterns, $operator, $isVerbose ) = @_;

    my $matchedCount = 0;

    my $line;
    my $fh = IO::File->new("<$logFilePath");
    if ( defined($fh) ) {
        my $fileSize = -s $logFilePath;
        if ( $fileSize > $maxSize ) {
            $fh->seek( -$maxSize, 2 );
        }

        do {
            $line = $fh->getline();
            if ( matchPatterns( $line, $patterns, $operator ) ) {
                if ( $isVerbose == 1 ) {
                    print($line);
                }

                $matchedCount = $matchedCount + 1;
            }
        } while ( defined($line) );

        $fh->close();
    }

    return $matchedCount;
}

sub main {
    my $rc = 0;

    my $pname = $FindBin::Script;

    my ( $isVerbose, $isFailCheck, $maxLogSize, $logPathPattern, $countExp, $patternOp, @patterns );

    $isVerbose   = 0;
    $isFailCheck = 1;
    $patternOp   = 'and';
    $maxLogSize  = 16;

    GetOptions(
        'verbose:i'   => \$isVerbose,
        'failcheck:i' => \$isFailCheck,
        'logpath:s'   => \$logPathPattern,
        'maxsize:i'   => \$maxLogSize,
        'op:s'        => \$patternOp,
        '<>'          => sub { my $item = shift(@_); push( @patterns, $item ); }
    );

    my $optError = 0;

    if ( not defined($logPathPattern) ) {
        $optError = 1;
        $rc       = 1;
        print("ERROR: Option --logpath not defined.\n");
    }

    if ( scalar(@patterns) == 0 ) {
        $optError = 1;
        $rc       = 1;
        print("ERROR: There is no pattern provided.\n");
    }

    if ( $optError == 1 ) {
        usage();
    }

    $maxLogSize = int($maxLogSize) * 1024 * 1024;

    my $matchedCount = 0;
    foreach my $logPath ( glob($logPathPattern) ) {
        $matchedCount = $matchedCount + matchLogLines( $logPath, $maxLogSize, \@patterns, $patternOp, $isVerbose );
    }

    my $satisfied = 0;
    if ( $matchedCount > 0 ) {
        $satisfied = 1;
    }

    if ($isFailCheck) {
        if ( $satisfied ne 1 ) {
            print("INFO: Log file had no fail key words.\n");
        }
        else {
            print("ERROR: Log file had fail key words.\n");
            $rc = 1;
        }
    }
    else {
        if ( $satisfied ne 1 ) {
            print("ERROR: Log file had no success key words.\n");
            $rc = 1;
        }
        else {
            print("INFO: Log file had success key words.\n");
        }
    }

    return $rc;
}

exit main();

